<?php
/*
 * @Author: your name
 * @Date: 2021-09-21 16:46:35
 * @LastEditTime: 2022-03-03 22:12:13
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /nlog/app/Http/Controllers/AdminController/Login.php
 */

namespace App\Http\Controllers\admin_controller;

use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\DB;
use \PhpOffice\PhpSpreadsheet\IOFactory;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\ExcelImport;



class Upload extends BaseController
{
    private string $fileKey = 'file';       //传入文件的key
    private string $manyfileKey = 'files';  //传入文件的key

    public function uploadOneFile()
    {
        // var_dump(  $_FILES);

        if (Request::hasFile($this->fileKey) && Request::has('fileType')) {
            $file =  $_FILES[$this->fileKey];
            $res =  Request::input('fileType') == 'possess' ? true :  $this->checkType($file['type'], Request::input('fileType')) && $this->checkSize($file['size'], 2 * 1024 * 1024);
            if ($res) {  //检查类型和大小
                return    $this->operation($file, Request::input('fileType'), Request::input('way'), Request::input('path'));
            } else {
                return $this->create(100, '文件类型或大小错误');
            }
        } else {
            return $this->create(100, '上传错误2', [], 501);
        }
    }

    //多图上传
    public function manyFile()
    {
        $file =  $_FILES;
        if (Request::has('fileType')) {
            $fileType = Request::input('fileType');
            $urlStr = '';
            foreach ($file as $key => $val) {
                if (preg_match('/' . $this->manyfileKey . '/', $key)) {
                    $file = $val;
                    if ($this->checkType($file['type'], $fileType) && $this->checkSize($file['size'], 2 * 1024 * 1024)) {  //检查类型和大小
                        $url =  $this->manyFileOperation($file, Request::input('fileType'), Request::input('path'));
                        if ($url) {
                            $urlStr .= $url . ',';
                        } else {
                            return  $this->create(100, '文件保存失败');
                        }
                    } else {
                        return  $this->create(100, '文件类型或大小错误');
                    }
                }
            }
            if ($urlStr) {
                return $this->create(200, '上传成功', substr($urlStr, 0, -1));
            }
        }
    }




    /**
     * @description: 文件操作
     * @param  file      文件
     * @param  fileType  文件类型
     * @param  way       导入的表名
     * @return bool
     */
    private function operation($file, $type, $way, $folder)
    {

        // if(empty($way)){
        // var_dump()
        $fileType = substr($file['name'], strrpos($file['name'], '.') + 1);  //获取文件类型

        $fileName = time() . rand(0, 100)  . '.' . $fileType;
        $path     = __PATH__;
        $url      = '/upload/' . ($folder ? $folder : $type) . '/';
        $path    .=   $url;
        $this->fileExists($path);                                //判断文件夹是否存在不存在则创建
        $path    .=  $fileName;                                  //绝对路径
        $res =   move_uploaded_file($file['tmp_name'], $path);   //临时路径 复制到 绝对路径
        $url     .=   $fileName;                                 //相对路径
        if ($res) {
            return  empty($way) ? $this->create(200, '上传成功', ['url' => $url]) : $this->theImport($path, $fileType, $way);
        } else {
            return $this->create(100, '上传失败');
        }
    }


    private function manyFileOperation($file, $type, $folder)
    {
        $fileType = substr($file['name'], strrpos($file['name'], '.') + 1);  //获取文件类型

        $fileName = time() . rand(0, 100)  . '.' . $fileType;
        $path     = __PATH__;
        $url      = '/upload/' . ($folder ? $folder : $type) . '/';
        $path    .=   $url;
        $this->fileExists($path);                                //判断文件夹是否存在不存在则创建
        $path    .=  $fileName;                                  //绝对路径

        $res =   move_uploaded_file($file['tmp_name'], $path);   //临时路径 复制到 绝对路径
        $url     .=   $fileName;                                 //相对路径

        return  $res ? $url : false;
    }


    /**
     * @description: 检查文件类型
     * @param  string $fileType 检查的文件类型
     * @param  string $type     对的类型
     * @return bool
     */
    private function checkType($fileType, $type)
    {
        $fileType = strtolower($fileType);
        switch ($type) {
            case 'excel':   //excel 文件上传
                if ($fileType == "application/vnd.ms-excel" || $fileType == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
                    return true;
                }
                return false;

            case 'images':
                if ($fileType == "image/png" || $fileType == "image/jpg" || $fileType == "image/gif" || $fileType == "image/jpeg") {

                    return true;
                }
                return false;
            case 'possess':
                return true;
            default:
                return false;
        }
    }




    /**
     * @description: 
     * @param  {*} $fileSize 文件大小
     * @param  {*} $Maxsize  最大的文件大小
     * @return {*}
     */
    private function checkSize($fileSize, $Maxsize)
    {
        if ($fileSize <= $Maxsize) {
            return true;
        }
        return false;
    }

    /**
     * @description:   提取数据后做的逻辑
     * @param string $path     
     * @param string $way      表名
     * @param string $fileType 文件类型
     * @return {*}
     */
    private function theImport($path, $fileType, $way)
    {
        $data =  $this->extract($path, $fileType);


        if (Request::has('onlyOne')) {
            $this->onlyOne($data, Request::input('onlyOne'), $way);
            die;
        }


        $array = $data['data'];              //excel数据


        if (Request::input('startSheet')) {   //是否规定从第几张表开始导入
            $startSheet = Request::input('startSheet');
            if ($startSheet > count($data)) {
                return  $this->create(100, '起始表大于总表数');
            }
            $startSheet = $startSheet - 1;  //从0开始  
        } else {
            $startSheet  = 0;
        }

        if (Request::input('endSheet')) {    //是否规定从第几张表结束
            $endSheet = Request::input('endSheet');
            if ($endSheet > count($data)) {
                return  $this->create(100, '结束表大于总表数');
            }
        } else {
            $endSheet  = count($array);
        }

        $sheetNames = $data['sheetNames'];    //工作表名称
        $mapping = $this->mappingSwitch($way);
        $int_Time =  $this->changeTime($way);       //数字转换为时间

        for ($i =  $startSheet; $i <  $endSheet; $i++) {
            $keyArrayCheck = $array[$i][1];       //每一个工作表的key
            $keyArray = [];
            $fieldMerge =  $this->fieldMerge($way);     //返回false时不进行合并
            for ($j = 0; $j < count($keyArrayCheck); $j++) {
                if ($keyArrayCheck[$j] != null &&  trim($keyArrayCheck[$j]) != '') {    //判断第二行key部是否为空
                    if (false !== $fieldMerge) {                               //是否需要合并字段
                        foreach ($fieldMerge as $key => $val) {
                            for ($z = 0; $z < count($val); $z++) {
                                if (strstr($keyArrayCheck[$j], $val[$z]['name'])) {                      //判断哪个字段要合并
                                    $num = ++$fieldMerge[$key][$z]['num'];
                                    //数据库字段名称,第一个
                                    $keyArrayCheck[$j] =  $key . '->' . ($val[$z]['jsonKey'] ?? '') . '=>' . $num;
                                    break;
                                }
                            }
                        }
                    }
                    $keyArray[$j] =  $keyArrayCheck[$j];
                }
            }
            $data = [];
            for ($j = 2; $j < count($array[$i]); $j++) {    //工作表内的数据
                $tmp = [];
                if ($array[$i][$j][0] != null && trim($array[$i][$j][0]) != '') {   //判断第一列序号是否为空
                    foreach ($keyArray as $key => $val) {                           //要存入的key
                        if ($int_Time) {                                              //需要转换时间
                            if (in_array($val, $int_Time) && is_numeric($array[$i][$j][$key])) {
                                $array[$i][$j][$key] =   $this->intChangeTime($array[$i][$j][$key]);
                            }
                        }
                        if (isset($mapping[$val])) {                               //判断映射数组是否存在
                            $tmp[$mapping[$val]] = $array[$i][$j][$key];
                        }


                        if ($fieldMerge && strstr($val, '->') &&  strstr($val, '=>')) {  //需要数据合并
                            list($field, $other)  =  explode('->', $val);
                            list($jsonKey, $number) =  explode('=>', $other);
                            $number = (int)$number;
                            $tmp[$field] ??  $tmp[$field] = [];                   //合并字段不存在则新建数组
                            $tmp[$field][$number] ?? $tmp[$field][$number] = [];  //合并字段不存在则新建数组
                            $array[$i][$j][$key] = $array[$i][$j][$key] != null && $array[$i][$j][$key] != '' ? $array[$i][$j][$key] : '';
                            if (empty($jsonKey)) {
                                $tmp[$field][$number] = $array[$i][$j][$key];            //二维数组
                            } else {
                                $tmp[$field][$number][$jsonKey]  = $array[$i][$j][$key]; //键值数组
                            }
                        }
                    }

                    if (!empty($tmp)) {
                        foreach ($tmp as $key => $val) {
                            if (is_array($val)) {        //如果为数组就转化成json添加到数据库里
                                $twoArray =  $this->keyArrayToTwo($val);
                                $tmp[$key]  = json_encode($twoArray, JSON_UNESCAPED_UNICODE);
                            }
                        }
                        $tmp['sheetName'] = $sheetNames[$i];      //工作表名称
                        $data[] = $tmp;
                    }
                }
            }

            if (!empty($data)) {
                DB::table($way)->insert($data);
            }
        }

        return $this->create(200, '导入成功');
    }

    //只导入一次
    private function onlyOne($data, $onlyOne, $way)
    {
        $all = [];

        if ($onlyOne == 'school') {
            $array = $data['data'][0];
            $type = '';
            $mappingSwitch = $this->mappingSwitch($way);
            for ($i = 3; $i < count($array); $i++) {
                $tmp = [];
                if (is_numeric($array[$i][0])) {
                    for ($j = 1; $j < count($array[$i]); $j++) {
                        $tmp[$mappingSwitch[$j]] = $array[$i][$j];
                    }
                    $tmp['province'] =  $type;
                    $tmp['school_type'] = '全国承认高等学校名单';
                    $all[] =  $tmp;
                } else {
                    $type =  explode('（', $array[$i][0])[0];
                }
            }
        }
        DB::table($way)->insert($all);
        // var_dump( $all);

    }



    /**
     * @description:    数据库表名
     * @param  array $way  返回映射数组
     * @return array
     */
    private function mappingSwitch($way)
    {
        if ($way == 'teaching_culture') {
            // [序号] => 3
            // [企业名称] => 中山新唐企业管理咨询有限公司
            // [注册地址] => 中山市三角镇南洋路1号粤林豪庭7幢25卡之一
            // [经营范围] => 艺术类
            // [成立日期] => 2014-05-05
            // [核准日期] => 2018-11-23
            // [法人] => 潘希肖
            // [工商手机号1] => 13802945020
            // [沟通跟进情况] => 
            // [查微信名称] => 
            // [加微信情况] => 
            // [工商手机号2] => 
            // [年报电话1] => 
            // [年报电话2] => 
            // [年报邮箱1] => 
            // [年报邮箱2] => 
            // [备注] => 
            return [
                '企业名称' => 'enterpriseName',
                '注册地址' => 'registeredAddress',
                '经营范围' => 'scopeBusiness',
                '成立日期' => 'setUpDate',
                '核准日期' => 'approvedDate',
                '法人' => 'legalPerson',
                '沟通跟进情况' => 'followUpSituation',
                '备注' => 'remark'
            ];
        } else if ($way == 'school') {
            //  return [
            //      1  => 'school_name',
            //      2  => 'identification',
            //      3  => 'competent',
            //      4  => 'location',
            //      5  =>  'education_level',
            //      6  =>  'remark'
            //  ];
            return [
                1  => 'school_name',
                2  => 'identification',
                3  => 'competent',

                4  =>  'remark'
            ];
        } else {
            return false;
        }
    }
    /** 
     * @description:      转化为时间格式
     * @param  way        表名
     * @return mixed
     */
    private function changeTime($way)
    {
        if ($way == 'teaching_culture') {
            return [
                '成立日期', '核准日期'
            ];
        } else {
            return false;
        }
    }



    /**
     * @description:  合并字段到一个字段
     * @param  way  表名
     * @return mixed
     */
    private function fieldMerge($way)
    {
        if ($way == 'teaching_culture') {
            return [
                'annalsPhone' => [              // 年报电话
                    [
                        'name' => '年报电话',
                        // 'jsonKey'=>false   ,      //false 时为一维数组
                        'jsonKey' => 'phone',
                        'num' => 0                    //出现几回
                    ]
                ],
                'annalsEmail' => [              // 年报邮箱 
                    [
                        'name' => '年报邮箱',
                        'jsonKey' => 'email',
                        'num' => 0                   //出现几回
                    ]

                ],
                'phoneMessage' => [             // 工商手机号 查微信名称 加微信情况 JSON形式
                    [
                        'name'   => '工商手机号',
                        'jsonKey' => 'phone',
                        'num'    => 0                   //工商手机号
                    ],
                    [
                        'name' => '查微信名称',
                        'jsonKey' => 'wechatName',
                        'num' => 0                   //查微信名称
                    ],
                    [
                        'name' => '加微信情况',
                        'jsonKey' => 'situation',
                        'num' => 0                   //加微信情况
                    ]
                ]
            ];
        } else {
            return false;
        }
    }



    /**
     * @description: 提取excel
     * @param  string $path      文件路径
     * @param  string $fileType  文件类型
     * @return array
     */
    private function extract($path, $fileType)
    {
        //https://www.cnblogs.com/windyet/articles/9711044.html           IOFactory类
        //https://docs.laravel-excel.com/3.1/imports/import-formats.html  Excel类
        $objReader = IOFactory::createReader(ucwords($fileType)); //首字母大写
        $objPHPExcel = $objReader->load($path);
        // // $sheetCount =  $objPHPExcel->getSheetCount(); //获取sheet工作表总个数
        $sheetNames =  $objPHPExcel->getSheetNames(); //获取sheet工作表名称
        $array =  Excel::toArray(new ExcelImport, $path);
        $this->fileUnlink($path);    //删除文件
        return ['data' => $array, 'sheetNames' => $sheetNames];
    }

    protected function fileExists($path)
    {
        if (!file_exists($path)) {
            return   mkdir($path, 0777, true); //判断保存目录是否存在，不存在自动生成文件目录
        }
    }

    protected function fileUnlink($path)
    {
        if (file_exists($path)) {
            return   unlink($path); //判断文件时否存在，存在就删除
        }
    }


    /**
     * @description:  Excel int转换时间
     * @param  int
     * @return date
     */
    private function  intChangeTime($time)
    {
        return      date('Y-m-d', ($time - 25569) * 24 * 3600);
    }


    /**
     * @description: 
     * @param {*} $array
     * @return {*}
     */
    private function keyArrayToTwo($array)
    {
        $data = [];
        foreach ($array as $val) {
            $data[] = $val;
        }
        return $data;
    }

    /**
     * @description:  导出用
     * @param  {*} $headStr  整个字符串
     * @param  {*} $text     后面拼接
     * @param  {*} $column   排序的
     * @return {*}
     */
    protected function setExcelHeader($headStr = '', $column = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
    {
        $columnStrlen = strlen($column);
        $first = substr($column, 0, 1);
        $last = substr($column, strlen($column) - 1, 1);
        $check = false;
        for ($j = strlen($headStr) - 1; $j > -1; $j--) {
            if ($last  != substr($headStr, $j, 1)) {
                $check  = $j;
                break;
            }
        }
        if (false === $check) {
            //  全部为Z的情况下加1全变成第一个
            $strlen  = strlen($headStr);
            $headStr = '';
            for ($j = 0; $j < $strlen; $j++) {
                $headStr .=   $first;
            }
            $headStr .=   $first;
        } else {
            $who = substr($headStr, $check, 1);      //哪一个不为最后一个
            $new = '';
            for ($j = 0; $j < $columnStrlen - 1; $j++) {           //倒数第二个
                if ($who ==  substr($column, $j, 1)) {
                    $new = substr($column, $j + 1, 1);
                    break;
                }
            }
            if ($check != strlen($headStr) - 1) {               //变的不是最后一个
                for ($j = $check + 1; $j < strlen($headStr); $j++) {
                    $headStr =  substr_replace($headStr, $first, $j, 1);
                }
            }
            $headStr = substr_replace($headStr, $new, $check, 1);
        }
        return  $headStr;
    }

    public function uploadGET()
    {



        if (Request::has('filePath') && is_file(__PATH__ . Request::input('filePath'))) {

            $file_xls = __PATH__ . Request::input('filePath');    //   文件的保存路径

            $example_name = Request::has('fileName') ? Request::input('fileName') : mb_convert_encoding(basename($file_xls), "gb2312", "utf-8");  //获取文件名
            //   $_POST['HTTP_SERVER']->header("Content-Description","File Transfer");
            //   $_POST['HTTP_SERVER']->header("Content-Type","application/octet-stream");
            //   $_POST['HTTP_SERVER']->header("Content-Disposition",'attachment; filename='. $example_name);
            //   $_POST['HTTP_SERVER']->header("Content-Transfer-Encoding","binary");
            //   $_POST['HTTP_SERVER']->header("Expires","0");
            //   $_POST['HTTP_SERVER']->header("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
            //   $_POST['HTTP_SERVER']->header("Pragma", "public");
            //   $_POST['HTTP_SERVER']->header("Content-Length", filesize($file_xls));

            $_POST['HTTP_SERVER']->header("Content-type", "application/octet-stream");
            $_POST['HTTP_SERVER']->header("Content-Disposition", "attachment;filename=" . $example_name);
            $_POST['HTTP_SERVER']->header("Accept-ranges", "bytes");
            $_POST['HTTP_SERVER']->header("Accept-length", filesize($file_xls));

            ob_clean();
            flush();
            readfile($file_xls);
        } else {
            return abort(404, '资源不存在');
        }
    }
}
